#include<bits/stdc++.h>
using namespace std;

#if 0
/// 传纸条 https://www.acwing.com/problem/content/277/
// 分两路，同时走
const int N = 55;
int a[N][N];
int f[2*N][N][N];
// 同时走，x1+y1 == x2+y2 = k
// f[k][i][j] 表示有两条路线都走k-1步，第一条路线到达(i,k-i), 第二条到达(j,k-j), 且两条路线不相交，能获得的最大好感度
int main()
{
    int n, m;
    cin >> n >> m; // n是行，m是列
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            cin >> a[i][j];

    for(int k = 2; k <= m+n; ++k)
        for(int i = 1; i <= n; ++i)
        {
            for(int j = 1; j <= n; ++j)
            {
                int y1 = k - i, y2 = k - j;
                // i == j时，说明相交了。由于i跟j都是在1~n，只需判断y1跟y2是否越界即可
                if(i == j || y1 <= 0 || y1 > m || y2 <= 0 || y2 > m) continue;
                f[k][i][j] = max(max(f[k-1][i][j], f[k-1][i][j-1]), max(f[k-1][i-1][j], f[k-1][i-1][j-1]));
                f[k][i][j] += a[i][k-i] + a[j][k-j];
                //printf("%d %d %d: %d\n", k, i, j, f[k][i][j]);
            }
        }
    //这里不会走到f[m+n][n][n], 因为会在右下角相遇。所以一个在左，一个在上
    printf("%d", f[m+n - 1][n - 1][n]); 
    return 0;
}

// 不相交的线 -- 友好城市 https://www.acwing.com/problem/content/1014/

// 法一：两个数组的dp，会超内存
const int N = 5010;
int a[N], b[N];
int dp[N][N];
int p[10010];
int n;

int main()
{
    cin >> n;
    for(int i = 1; i <= n; ++i)
    {
        cin >> a[i] >> b[i];
        p[a[i]] = b[i];
    }
    sort(a + 1, a + n + 1);
    sort(b + 1, b + n + 1);
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= n; ++j)
        {
            if(p[a[i]] == b[j])
                dp[i][j] = dp[i - 1][j - 1] + 1;
            else
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            printf("%d, %d: %d\n", i, j, dp[i][j]);
        }
    }
    cout << dp[n][n];
    return 0;
}


// 法二：最长上升子序列
const int N = 5010;
int n;
pair<int,int> a[N];
int dp[N];

struct cmp
{
    bool operator()(const pair<int,int>& p1, const pair<int,int>& p2) const
    {
        return p1.first < p2.first;
    }
};

int main()
{
    cin >> n;
    for(int i = 0; i < n; ++i)
    {
        cin >> a[i].first >> a[i].second;
    }
    sort(a, a + n, cmp());
    
    int ret = 0;
    for(int i = 0; i < n; ++i)
    {
        dp[i] = 1;
        for(int j = i - 1; j >= 0; --j)
            if(a[i].second > a[j].second)
                dp[i] = max(dp[i], dp[j] + 1);
        ret = max(ret, dp[i]);
    }
    cout << ret;
    return 0;
}
#endif 

// 拦截导弹 https://www.acwing.com/problem/content/1012/
const int N = 1010;
int a[N], f[N], len[N], n;
int pre[N];
bool st[N];

int find(int i)
{
    int l = 1, r = n;
    while(l < r)
    {
        int mid = (l + r) >> 1;
        if(a[len[mid]] >= a[i]) l = mid + 1;
        else r = mid;
    }
    return l;
}

int main()
{
    a[0] = -1e9;
    string s;
    getline(cin, s);
    int m = s.size();
    for(int i = 0; i < m; ++i)
    {
        int t = 0;
        if(s[i] >= '0' && s[i] <= '9')
        {
            while(i < m && s[i] >= '0' && s[i] <= '9')
            {
                t = t * 10 + s[i] - '0';
                ++i;
            }
            a[++n] = t;
            --i;
        }
    }

    int cnt = 0, ret = 0, c = 0, ans = 0;
    while(cnt < n)
    {
        memset(len, 0, sizeof len);
        for(int i = 1; i <= n; ++i)
        {
            if(st[i]) continue;
            
            int p = find(i);
            len[p] = i;
            f[i] = p;
            pre[i] = len[p - 1];
            if(f[i] > f[ret]) ret = i;
            //printf("%d: %d\n", i, f[i]);
        }
        if(f[ret] > f[ans])
            ans = ret;
        while(ret)
        {
            ++cnt;
            st[ret] = true;
            ret = pre[ret];
        }
        ++c;
        puts("");
    }
    
    printf("%d\n%d\n", f[ans], c);
    return 0;
}